package com.yeung.aop.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.Arrays;
import java.util.List;

/**
 * 把这个类声明为一个切面: 需要把类放入到IOC容器中\在声明为一个切面
 */
public class LogingAspect {
    //该方法是一个前置通知:在目标方法开始执行之前执行
    //* 是一个通配符,表示所有方法执行之前
    public void beforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();//执行的方法名
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println(methodName + "-> the method begins" + ": " + args.toString());
    }

    /**
     * 后置通知: 在目标方法执行后,执行的通知
     *
     * @param joinPoint
     */
    public void afterMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();//执行的方法名
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println(methodName + "-> the method end " + ": " + args.toString());

    }

    /**
     * 在方法正常结束时执行的代码
     * 返回通知是可以访问到方法的返回值的!!!
     *
     * @param joinPoint
     */
    public void afterRunning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();//执行的方法名
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println(methodName + "-> the method end " + ": with= " + result);

    }

    /**
     * 方法出现异常时会执行的代码,
     * 可以访问得到异常,且可以指定在出现特定异常是执行通知代码
     *
     * @param joinPoint
     */
    public void afterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();//执行的方法名
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println(methodName + "-> the method " + ": occurs exception: " + ex);

    }

    /**
     * 环绕通知相当于动态代理的全过程
     * 需要携带ProceedingJoinPoint类型的参数
     * 改参数决定是否执行目标方法
     * 且必须有返回值,为目标方法的返回值
     * <p>
     * 功能最强, 但不常用!!!
     *
     * @param joinPoint
     */
    public Object aroundMethod(ProceedingJoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();//执行的方法名
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("环绕通知");
        Object result = null;
        try {
            //前置通知
            System.out.println(methodName + "-> the method begins" + ": " + args.toString());
            result = joinPoint.proceed();
            //返回通知,可以访问得到方法的返回值
            System.out.println(" the method is completed, result=" + result);
        } catch (Exception e) {
            //异常通知,可以访问到方法出现的异常
        } catch (Throwable throwable) {
            System.out.println(methodName + "-> the method " + ": occurs exception: " + throwable.getMessage());
        }
        //后置通知,因为方法可能会出异常,所以访问不到方法的返回值
        System.out.println(methodName + "-> the method ends " + ": " + args.toString());
        //日志

        return result;
    }
}
